#include <math.h>

/***********************************************************************************************************
 * Returns mimimum of a and b
 ***********************************************************************************************************/
template<typename T> T RBMath::Min(T a, T b)
{
	return (a<b) ? a : b;
}

/***********************************************************************************************************
 * Returns maximum of a and b
 ***********************************************************************************************************/
template<typename T> T RBMath::Max(T a, T b)
{
	return (a>b) ? a : b;
}


template<typename T>
T RBMath::Clamp( T val, T min_val, T max_val )
{
    return (val < min_val) ? min_val : (val > max_val) ? max_val : val;
}

/***********************************************************************************************************
 * Returns absolute value of a
 ***********************************************************************************************************/
template<typename T> T RBMath::Abs(T a)
{
	return (a>0) ? a : -a;
}

/***********************************************************************************************************
 *
 ***********************************************************************************************************/
template<typename T>
T RBMath::Sign(T a)
{
    return (a>0) ? static_cast<T>(1) : (a<0) ? static_cast<T>(-1) : static_cast<T>(0);

}

/***********************************************************************************************************
 * Returns absolute value of a
 ***********************************************************************************************************/
template<typename T> T RBMath::FMod(T f, T mod)
{
    return static_cast<T>(fmod(f, mod));
}

inline float32 RBMath::RandUnit()
{
    return static_cast<float32>(((float32)RBSystem::Rand())/((float32)RBSystem::RB_RAND_MAX));
}

/***********************************************************************************************************
 * Returns square root of f
 ***********************************************************************************************************/
template<typename Ret, typename T> Ret RBMath::Sqrt(T f)
{
	return static_cast<Ret>(sqrt((float32)f));
}

/***********************************************************************************************************
 * Returns square root of f
 ***********************************************************************************************************/
template<typename Ret, typename T> Ret RBMath::Tan(T f)
{
	return static_cast<Ret>(tan((float32)f));
}

/**************************************************************************************************************************************************************
 * 
 **************************************************************************************************************************************************************/
template<typename Ret, typename T> void RBMath::SinCos(T f, Ret& sn, Ret& cs)
{
    float s, c;
    __asm fld f
    __asm fsincos
    __asm fstp c
    __asm fstp s

    sn = static_cast<Ret>(s);
    cs = static_cast<Ret>(c);
}

/**************************************************************************************************************************************************************
 * 
 **************************************************************************************************************************************************************/
template<typename T> T RBMath::ToRadian(T f)
{
    return f * RB_PI / 180.0f;
}

/**************************************************************************************************************************************************************
 * 
 **************************************************************************************************************************************************************/
template<typename T> T RBMath::ToDegrees(T f)
{
    return f * 180.0f / RB_PI;
}



inline int32 RBMath::Round( float32 a )
{
    return (a>=0.0f) ? int32(a+0.5f) : int32(a-0.5f);
}



inline uint32 align_above( uint32 val, uint32 align )
{
    uint32 mask = align-1;
    return (val+mask) & (~mask);
}

